/*
 * Copyright (c) 2010 CCX(China) Co.,Ltd. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * CCX(China) Co.,Ltd. ("Confidential Information").
 * It may not be copied or reproduced in any manner without the express 
 * written permission of CCX(China) Co.,Ltd.
 *
 * Author: zhaosj
 * Date: 2011-1-6 下午03:48:12
 */
package com.excelplugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import jxl.Cell;
import jxl.NumberCell;
import jxl.Sheet;
import jxl.Workbook;

import com.dbpool.BoneCPs;
import com.excelplugin.vo.FunctionDetail;
import com.excelplugin.vo.FunctionParaType;
import com.excelplugin.vo.FunctionParameter;
import com.util.PinyinConvert;

/**
 * @author zhaosj
 * 
 */
public class FunctionImport {

	public static String fileName = "F:\\MYDOCUMENT\\ExcelPlugin\\文档\\落地数据准备\\指标函数整理.xls";
	public static String polyphoneFile = "F:\\MYDOCUMENT\\ExcelPlugin\\文档\\落地数据准备\\特殊数据处理.sql";

	/**
	 * 指标函数的参数类型
	 */
	public static Map<String, String> paraTypeMap = new HashMap<String, String>() {

		private static final long serialVersionUID = 2772335870387945464L;

		{
			put("code", "string");
			put("vtype", "int");
			put("reportdate", "date");
			put("startdate", "date");
			put("enddate", "date");
			put("year", "year");
			put("vdate", "date");
			put("n", "int");
			put("itemcode", "int");
			put("term", "int");
			put("k", "int");
			put("price", "string");
		}
	};

	/**
	 * 参数中英名称
	 */
	public static Map<String, String> paraNameMap = new HashMap<String, String>() {

		private static final long serialVersionUID = 4248621814134671938L;

		{
			put("code", "代码");
			put("vtype", "类型");
			put("reportdate", "报告期");
			put("startdate", "开始日期");
			put("enddate", "结束日期");
			put("year", "年度");
			put("vdate", "日期");
			put("n", "N年");
			put("itemcode", "编码");
			put("term", "期限");
			put("k", "K年");
			put("price", "价格");
		}
	};

	/**
	 * 参数的说明信息
	 */
	public static Map<String, String> paraDesMap = new HashMap<String, String>() {

		private static final long serialVersionUID = 640135809211357236L;

		{
			put("code", "中诚信代码，比如 600000.SH");
			put("vtype", "document");
			put("reportdate", "报告期，比如 2010-12-31");
			put("startdate", "开始日期，比如 2010-12-31");
			put("enddate", "结束日期，比如 2010-12-31");
			put("year", "年度，比如 2010");
			put("vdate", "日期，比如 2010-12-31");
			put("n", "年限，比如 3");
			put("itemcode", "指标编码");
			put("term", "期限，比如 3");
			put("k", "年限，比如 3");
			put("price", "价格，比如 100");
		}

	};

	/**
	 * 参数的控件类型：1-文本框；2-下拉列表；3-日期控件；4-具有搜索功能的下拉框；
	 */
	public static Map<String, Integer> paraCtlTypeMap = new HashMap<String, Integer>() {

		private static final long serialVersionUID = 640135809211357236L;

		{
			put("code", 4); // 证券代码参数采用“键盘精灵”模式
			put("vtype", 2);
			put("reportdate", 2);
			put("startdate", 3);
			put("enddate", 3);
			put("year", 2);
			put("vdate", 3);
			put("n", 2);
			put("itemcode", 2);
			put("term", 2);
			put("k", 2);
			put("price", 1);
		}
	};

	/**
	 * 参数是否可以使用鼠标选择输入： 0-不使用；1-使用
	 */
	public static Map<String, Integer> paraSelbuttonMap = new HashMap<String, Integer>() {

		private static final long serialVersionUID = -2014895411899245642L;

		{
			put("code", 1);
			put("vtype", 0);
			put("reportdate", 1);
			put("startdate", 1);
			put("enddate", 1);
			put("year", 1);
			put("vdate", 1);
			put("n", 1);
			put("itemcode", 0);
			put("term", 1);
			put("k", 1);
			put("price", 1);
		}
	};

	/**
	 * 主方法：导入指标函数信息
	 */
	public void ImportFunctionInfo() {
		try {
			Connection con = BoneCPs.getConnection("funcOracle");

			// 打开EXCEL文档
			Workbook wb = Workbook.getWorkbook(new File(fileName));
			Sheet ws = wb.getSheet("Sheet2");
			Sheet typeWs = wb.getSheet("type参数");

			Cell cell = null;
			NumberCell nc = null;

			int rows = ws.getRows(); // 文档总行数
			int cols = ws.getColumns(); // 文档总列数

			System.out.println("rows=" + rows);
			System.out.println("cols=" + cols);

			// 读取文档表单 sheet1，处理所有指标函数（遍历每一行）
			for (int r = 1; r < rows; r++) {

				// 函数详情类
				FunctionDetail vfd = new FunctionDetail();

				// 函数参数类
				FunctionParameter vfp = new FunctionParameter();

				// 多值参数类(type)
				FunctionParaType vfpt = new FunctionParaType();

				int isLeaf = 0; // 是否叶子节点
				int isOverload = 0; // 是否重载指标编码
				int hasType = 0; // 是否有'TYPE'参数（或者类似TYPE，有多值的参数）
				int isShowChild = 0; // 在前台选中自身时，是否显示子节点
				int funcStatus = 0; // 函数显示状态 0-隐藏；1-显示
				int itemcodeStatus = 0; // 重载函数（指标编码）显示状态 0-隐藏；1-显示
				int funcOrder = 1; // 层内排序号
				int hasExpression = 0;// 是否导入指标表达式
				int funcModule = 0;//指标所属模块 0-通用；1-财务；2-实时行情；3-历史行情；
				int funcCategory = 0;// 指标分类  0-无分类；1-债券；2-股票；3-基金；4-指数；5-利率
				int funcUnit = 0; //指标函数的单位  0-无单位,1-(元),2-(%),3-(天/次),4-(次),5-(倍),6-(元/股),7-(人),8-(股/户),9-(户),10-(股),11-(天),12-(家),13-(张),14-(年),15-(手)
				long funcParentId = 0; // 函数父ID
				long funcId = 0; // 函数ID

				String funcName = ""; // 函数名称
				String funcExpression = ""; // 函数表达式
				String funcDescription = "";// 函数描述
				String overLoadName = ""; // 指标编码重载名，用于查找相应的SHEET

				// 用于判断表达式中左右括弧的位置，来分析参数
				int leftBracket = 0;
				int rightBracket = 0;

				String paramStr = ""; // 参数串
				String[] paramArray = null; // 参数数组

				// 指标ID
				funcId = (long) ((NumberCell) ws.getCell(5, r)).getValue();
				vfd.setFuncId(funcId);
				vfp.setFuncId(funcId);

				// 指标父ID
				funcParentId = (long) ((NumberCell) ws.getCell(4, r)).getValue();
				vfd.setFuncParentId(funcParentId);

				// 指标函数名称
				funcName = getFunctionName(ws, r).trim();
				vfd.setFuncName(funcName);

				// 指标函数名称拼音首字母
				vfd.setFuncNamePy(PinyinConvert.cn2py(funcName));

				// 指标函数备注
				funcDescription = funcName;
				vfd.setFuncDescription(funcDescription);

				// 是否显示子列表
				isShowChild = (int) ((NumberCell) ws.getCell(3, r)).getValue();
				vfd.setIsShowChild(isShowChild);

				// 是否有TYPE参数(或者类似TYPE的参数，此类参数有多值)
				hasType = (int) ((NumberCell) ws.getCell(2, r)).getValue();

				// 是否有ITEMCODE参数
				isOverload = (int) ((NumberCell) ws.getCell(1, r)).getValue();
				vfd.setIsOverload(isOverload);

				// 是否叶子节点
				cell = ws.getCell(0, r);
				nc = (NumberCell) cell;
				isLeaf = (int) nc.getValue();
				vfd.setIsLeaf(isLeaf);

				// 显示状态
				cell = ws.getCell(14, r);
				nc = (NumberCell) cell;
				funcStatus = (int) nc.getValue();
				vfd.setFuncStatus(funcStatus);

				// 层内排序号
				cell = ws.getCell(15, r);
				nc = (NumberCell) cell;
				funcOrder = (int) nc.getValue();
				vfd.setFuncOrder(funcOrder);

				// 是否导入指标表达式
				cell = ws.getCell(16, r);
				nc = (NumberCell) cell;
				hasExpression = (int) nc.getValue();

				//指标所属业务模块 ：0-普通；1-财务；2-实时行情；3-历史行情；4-衍生数据
				cell = ws.getCell(17, r);
				nc = (NumberCell) cell;
				funcModule = (int) nc.getValue();
				vfd.setFuncModule(funcModule);

				//指标所属分类 ： 1-债券；2-股票；3-基金；4-指数
				cell = ws.getCell(18, r);
				nc = (NumberCell) cell;
				funcCategory = (int) nc.getValue();
				vfd.setFuncCategory(funcCategory);

				//指标单位 ： 0-无单位,1-(元),2-(%),3-(天/次),4-(次),5-(倍),6-(元/股),7-(人),8-(股/户),9-(户),10-(股),11-(天),12-(家),13-(张),14-(年),15-(手),16-(万元)
				cell = ws.getCell(19, r);
				nc = (NumberCell) cell;
				funcUnit = (int) nc.getValue();
				vfd.setFuncUnit(funcUnit);

				// 判断是否叶子节点，需要获取表达式和对应函数 ====================================
				if (hasExpression == 1) {

					// 获取表达式原型，根据参数的个数和名称，获取对应的参数中文名和参数顺序；
					funcExpression = ws.getCell(11, r).getContents();
					funcExpression = funcExpression.trim().toLowerCase();

					if (funcModule != 2) //如果不是实时行情，就做指标参数的处理
					{
						funcExpression = funcExpression.replaceAll(",type", ",vtype");
						funcExpression = funcExpression.replaceAll(",date", ",vdate");
						funcExpression = funcExpression.replaceAll("\\(date", "\\(vdate");

						leftBracket = funcExpression.indexOf("(");
						rightBracket = funcExpression.lastIndexOf(")");

						paramStr = funcExpression.substring(leftBracket + 1, rightBracket); // 参数串
						paramArray = paramStr.split(","); // 参数数组

						// 获取参数信息，写入数据库
						for (int p = 0; p < paramArray.length; p++) {
							long paraId = getMaxParamterId(con, "vba_function_parameter", "para_id");
							String paramNameEn = paramArray[p].trim();
							String paramNameCn = paraNameMap.get(paramNameEn);

							if (("vtype".equals(paramNameEn)) || ("n".equals(paramNameEn)) || ("k".equals(paramNameEn))
									|| ("term".equals(paramNameEn))) // 如果参数是type、n、k、term，则从名为“type参数”的sheet中获取参数列表
							{
								vfp.setIsMultiValue(hasType);
								vfp.setParaDescription(getFuncParaDesc(typeWs, funcId, paramNameEn));
								vfpt.setParaId(paraId);

								// 根据函数ID获取TYPE参数列表
								String[][] types = getFuncParaType(typeWs, funcId, paramNameEn);
								for (int t = 0; t < types.length; t++) {
									long typeId = getMaxParamterId(con, "vba_function_para_type", "type_id");
									vfpt.setTypeId(typeId);
									vfpt.setTypeCode(Integer.parseInt(types[t][0]));
									vfpt.setTypeName(types[t][1]);
									vfpt.setTypeNamePy(PinyinConvert.cn2py(types[t][1]));
									vfpt.setTypeDescription("" + types[t][1]);
									vfpt.setTypeOrder(t + 1);
									vfpt.setTypeStatus(1);
									vfpt.setTypeUnit(0);

									// type参数入库
									insertVfpt(vfpt, con);

								}

							} else if ("itemcode".equals(paramNameEn)) // 参数是ITEMCODE
							{
								vfp.setIsMultiValue(2);
								vfp.setParaDescription(paraDesMap.get(paramNameEn));
								vfpt.setParaId(paraId);

								// 根据重载名找到对应的SHEET
								overLoadName = ws.getCell(13, r).getContents();
								Sheet itemWs = wb.getSheet(overLoadName);

								System.out.println("overload name ==========================" + overLoadName);
								int itemRows = itemWs.getRows();
								int itemCode = 0;
								int itemUnit = 0;
								String itemName = "";

								for (int ir = 1; ir < itemRows; ir++) {
									long typeId = getMaxParamterId(con, "vba_function_para_type", "type_id");
									vfpt.setTypeId(typeId);

									// 获取指标编码名称
									cell = itemWs.getCell(0, ir);
									itemName = cell.getContents();
									vfpt.setTypeName(itemName);
									vfpt.setTypeNamePy(PinyinConvert.cn2py(itemName));

									// 获取指标编码
									cell = itemWs.getCell(1, ir);
									itemCode = (int) ((NumberCell) cell).getValue();
									vfpt.setTypeCode(itemCode);

									// 决定客户端是否展现的标志：0-不展现；1-展现；
									cell = itemWs.getCell(2, ir);
									itemcodeStatus = (int) ((NumberCell) cell).getValue();
									vfpt.setTypeStatus(itemcodeStatus);

									//指标的单位
									cell = itemWs.getCell(3, ir);
									itemUnit = (int) ((NumberCell) cell).getValue();
									vfpt.setTypeUnit(itemUnit);

									vfpt.setTypeDescription(itemName);
									vfpt.setTypeOrder(ir);

									// type参数入库
									insertVfpt(vfpt, con);
								}

							} else // 普通参数
							{
								vfp.setIsMultiValue(0);
								vfp.setParaDescription(paraDesMap.get(paramNameEn));
							}

							vfp.setFuncId(funcId);
							vfp.setParaId(paraId);
							vfp.setParaNameEn(paramNameEn);
							vfp.setParaNameCn(paramNameCn);
							vfp.setParaType(paraTypeMap.get(paramNameEn));
							vfp.setParaOrder(p + 1);
							vfp.setParaCtlType(paraCtlTypeMap.get(paramNameEn));
							vfp.setParaSelbutton(paraSelbuttonMap.get(paramNameEn));

							// 插入函数参数表
							insertVfp(vfp, con);
						}

						// 把函数表达式的参数名称替换为汉字
						String leftExpression = funcExpression.substring(0, leftBracket);
						String funcExpression02 = paramStr;
						funcExpression02 = funcExpression02.replaceAll(",vtype", "," + paraNameMap.get("vtype"));
						funcExpression02 = funcExpression02.replaceAll(",reportdate", "," + paraNameMap.get("reportdate"));
						funcExpression02 = funcExpression02.replaceAll(",startdate", "," + paraNameMap.get("startdate"));
						funcExpression02 = funcExpression02.replaceAll(",enddate", "," + paraNameMap.get("enddate"));
						funcExpression02 = funcExpression02.replaceAll(",year", "," + paraNameMap.get("year"));
						funcExpression02 = funcExpression02.replaceAll(",vdate", "," + paraNameMap.get("vdate"));
						funcExpression02 = funcExpression02.replaceAll(",n", "," + paraNameMap.get("n"));
						funcExpression02 = funcExpression02.replaceAll(",itemcode", "," + paraNameMap.get("itemcode"));
						funcExpression02 = funcExpression02.replaceAll("code", paraNameMap.get("code"));
						funcExpression02 = funcExpression02.replaceAll("price", paraNameMap.get("price"));
						funcExpression02 = funcExpression02.replaceAll("vdate,", paraNameMap.get("vdate") + ",");
						funcExpression02 = funcExpression02.replaceAll("term,", paraNameMap.get("term") + ",");
						funcExpression02 = funcExpression02.replaceAll("k,", paraNameMap.get("k") + ",");

						vfd.setFuncExpression(leftExpression.trim() + "(" + funcExpression02.trim() + ")");
					} else //如果是实时行情，则指标没有参数
					{
						vfd.setFuncExpression(funcExpression);
					}

				} else
					// 非叶子节点，没有函数表达式
					vfd.setFuncExpression("");

				// 插入函数详情表
				insertVfd(vfd, con);

			}

			// 处理中文名称拼音缩写多音字问题
			disposePolyphone(con);

			wb.close();
			con.close();

		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	/**
	 * 添加“函数参数表”新记录：vba_function_parameter
	 * 
	 * @param vfp
	 * @param con
	 */
	public void insertVfp(FunctionParameter vfp, Connection con) {
		try {
			String sql = "insert into vba_function_parameter(para_id,func_id,para_name_en,para_name_cn,para_description,para_type,para_order,is_multivalue,para_ctl_type,para_selbutton) values(?,?,?,?,?,?,?,?,?,?)";
			PreparedStatement ps = con.prepareStatement(sql);
			ps.setLong(1, vfp.getParaId());
			ps.setLong(2, vfp.getFuncId());
			ps.setString(3, vfp.getParaNameEn());
			ps.setString(4, vfp.getParaNameCn());
			ps.setString(5, vfp.getParaDescription());
			ps.setString(6, vfp.getParaType());
			ps.setInt(7, vfp.getParaOrder());
			ps.setInt(8, vfp.getIsMultiValue());
			ps.setInt(9, vfp.getParaCtlType());
			ps.setInt(10, vfp.getParaSelbutton());

			ps.executeUpdate();

			ps.close();

		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	/**
	 * 添加“函数详情表”新记录：vba_function_detail
	 * 
	 * @param vfd
	 * @param con
	 */
	public void insertVfd(FunctionDetail vfd, Connection con) {
		try {
			String sql = "insert into vba_function_detail(func_id,func_name,func_name_py,func_expression,func_description,is_show_child,is_overload,is_leaf,func_status,func_parent_id,func_order,func_module,func_category,func_unit) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
			PreparedStatement ps = con.prepareStatement(sql);
			ps.setLong(1, vfd.getFuncId());
			ps.setString(2, vfd.getFuncName());
			ps.setString(3, vfd.getFuncNamePy());
			ps.setString(4, vfd.getFuncExpression());
			ps.setString(5, vfd.getFuncDescription());
			ps.setInt(6, vfd.getIsShowChild());
			ps.setInt(7, vfd.getIsOverload());
			ps.setInt(8, vfd.getIsLeaf());
			ps.setInt(9, vfd.getFuncStatus());
			ps.setLong(10, vfd.getFuncParentId());
			ps.setInt(11, vfd.getFuncOrder());
			ps.setInt(12, vfd.getFuncModule());
			ps.setInt(13, vfd.getFuncCategory());
			ps.setInt(14, vfd.getFuncUnit());

			ps.executeUpdate();

			ps.close();

		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	/**
	 * 添加“多值参数表”记录 ：vba_function_para_type
	 * 
	 * @param vfpt
	 * @param con
	 */
	public void insertVfpt(FunctionParaType vfpt, Connection con) {
		try {
			String sql = "insert into vba_function_para_type(type_id,para_id,type_code,type_name,type_description,type_order,type_status,type_name_py,type_unit) values (?,?,?,?,?,?,?,?,?)";
			PreparedStatement ps = con.prepareStatement(sql);
			ps.setLong(1, vfpt.getTypeId());
			ps.setLong(2, vfpt.getParaId());
			ps.setInt(3, vfpt.getTypeCode());
			ps.setString(4, vfpt.getTypeName());
			ps.setString(5, vfpt.getTypeDescription());
			ps.setInt(6, vfpt.getTypeOrder());
			ps.setInt(7, vfpt.getTypeStatus());
			ps.setString(8, vfpt.getTypeNamePy());
			ps.setInt(9, vfpt.getTypeUnit());

			ps.executeUpdate();

			ps.close();

		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	/**
	 * 获取表中最大主键ID
	 * 
	 * @param con
	 *            链接
	 * @param tableName
	 *            表名
	 * @param field
	 *            字段名
	 * @return
	 */
	public long getMaxParamterId(Connection con, String tableName, String field) {
		long maxParaId = 0;
		try {
			String sql = "select max(" + field + ") as " + field + " from " + tableName;
			PreparedStatement ps = con.prepareStatement(sql);

			ResultSet rs = ps.executeQuery();

			while (rs.next()) {
				maxParaId = rs.getLong(field) + 1;
			}

			rs.close();
			ps.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

		return maxParaId;
	}

	/**
	 * 获取函数名称
	 * 
	 * @param ws
	 *            指标函数EXCEL文档
	 * @return
	 */
	public String getFunctionName(Sheet ws, int row) {
		Cell cell = null;
		String name = "";
		// 从第row行，第6-10列中提取指标名称（或分类名称）
		for (int c = 6; c <= 10; c++) {
			cell = ws.getCell(c, row);
			if (cell != null)
				name = cell.getContents();
			if (!"".equals(name))
				break;
		}

		return name;
	}

	/**
	 * 根据函数ID和参数名称，查找该参数的数据列表
	 * 
	 * @param typeWs
	 *            包含TYPE列表信息的SHEET
	 * @param funcId
	 *            待搜索的函数ID
	 * @return
	 */
	public String[][] getFuncParaType(Sheet typeWs, long funcId, String paraNameEn) {
		int cols = typeWs.getColumns();
		int rows = typeWs.getRows();
		ArrayList<String> al = new ArrayList<String>();

		// 根据函数ID搜索到某行，获取该函数的TYPE参数列表
		for (int r = 1; r < rows; r++) {
			if (((long) ((NumberCell) typeWs.getCell(1, r)).getValue() == funcId) && (paraNameEn.equals(typeWs.getCell(2, r).getContents().trim()))) {
				for (int c = 3; c < cols; c++) {
					String types = typeWs.getCell(c, r).getContents();
					if (!"".equals(types)) {
						al.add(types);

					} else
						break;
				}
			}
		}

		String[][] typeArray = new String[al.size()][2];
		for (int c = 0; c < al.size(); c++) {
			String str = al.get(c);
			int minusToken = str.indexOf("-");
			typeArray[c][0] = str.substring(0, minusToken);
			typeArray[c][1] = str.substring(minusToken + 1);
		}

		return typeArray;
	}

	/**
	 * 根据函数ID和参数名称，查找到该参数的数据列表
	 * 
	 * @param typeWs
	 * @param funcId
	 * @param paraNameEn
	 * @return
	 */
	public String getFuncParaDesc(Sheet typeWs, long funcId, String paraNameEn) {

		int rows = typeWs.getRows();
		String paraDesc = "";

		// 根据函数ID搜索到某行，获取该函数的TYPE参数列表
		for (int r = 1; r < rows; r++) {
			if (((long) ((NumberCell) typeWs.getCell(1, r)).getValue() == funcId) && (paraNameEn.equals(typeWs.getCell(2, r).getContents().trim()))) {
				paraDesc = typeWs.getCell(0, r).getContents();
			}
		}

		return paraDesc;
	}

	/**
	 * 处理指标中文名称拼音缩写多音字
	 * 
	 * @param con
	 */
	public void disposePolyphone(Connection con) {

		String line = null;

		try {

			BufferedReader br = new BufferedReader(new FileReader(polyphoneFile));
			while ((line = br.readLine()) != null) {
				if (!"".equals(line) && !line.startsWith("--")) {

					PreparedStatement ps = con.prepareStatement(line);
					ps.execute();
					ps.close();

				} else
					System.out.println(line);
			}

			br.close();

		} catch (Exception e) {
			System.out.println(line);

			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

		long startTime = System.currentTimeMillis();

		FunctionImport vfi = new FunctionImport();
		vfi.ImportFunctionInfo();

		long endTime = System.currentTimeMillis();

		System.out.println("OVER!\n" + (endTime - startTime));

	}
}
